var http = require('http')
, app = http.createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
, url = require('url')
, config = require('./config.js')

app.listen(8080);

//config = fs.readFileSync("config");


function handler (req, res) {
	var path = url.parse(req.url).pathname;
	if (/\.css$/.test(path)){
		res.writeHead(200, {'Content-Type': 'text/css'});
		res.write(fs.readFileSync(__dirname + '/style.css', 'utf8')); // <- + path OR + 'bla'
		res.end();
	} else {
		fs.readFile(__dirname + '/app.html',
		function (err, data) {
			if (err) {
				res.writeHead(500);
				return res.end('Error loading index.html');
			}

			res.writeHead(200);//, {'Content-Type': 'text/html'});
			res.end(data.toString().replace(new RegExp(config.nodejs_url_from, 'g'), config.nodejs_url));
		});
	}
}
var debug = false
var x = 3
var y = 3
//Only one player
if(debug) {
	board = [['o', 'x', 'o'],[0, 0, 0],[0, 0, 0]]//0 - empty, 1 - x, 2 -
} else {
	//TODO: board by matchId
	//Assoc
	board = {}
	/*
	for (var i = 0; i < x; i++) {
		board[i] = []
		for (var j = 0; j < y; j++)
			board[i][j] = 0;
	}*/
	turns = []
	//board = [[0, 0, 0],[0, 0, 0],[0, 0, 0]]
}
var firstPlayerId = 0//
var firstPlayerType = 'x'
var startType = 'x'
var turnForType = 'x'
var secondPlayerId = 0
var secondPlayerType = 'o'

//var users = {};
//var userNumber = 0;
//var sessionIdByUserId = {};
//var userIdBySessionId = {};
/*
match(
board
firstPlayerId
firstPlayerType
secondPlayerId
secondPlayerType
startType
turnForType
moves_log
)
*/
var match = {};
//~ var web2py_url="http://127.0.0.1:8000/smartgames/game/"
//var web2py_url="http://jurgis.pythonanywhere.com/smartgames/game/"
function inv(type) {
	return type == 'x' ? 'o' : 'x'
}
io.sockets.on('connection', function (socket) {
	//Local vars:
	//console.log(socket);
	//if(firstPlayerId == 0 || secondPlayerId == firstPlayerId)
	//secondPlayerId = socket.id;
	
	//MOVED:
	//if(firstPlayerId != secondPlayerId && secondPlayerId != 0)
	//	socket.emit(secondPlayerType == turnForType ? 'yourTurn' : 'notYourTurn');
	var matchId, playerId, action, secKey;
	var playerI = undefined;
	function game() { return match[matchId]	}
	function isYourTurn(matchId, soc_id) {
		return (game()['turnForType'] == game()['playersType'][0]
			 && game()['playersSoc'][0] == soc_id
			 || game()['turnForType'] == game()['playersType'][1]
			 && game()['playersSoc'][1] == soc_id)
	}

	socket.on('introduce', function (data) {
		console.log('got introduce', data);
		playerId = data.playerId;
	});

	socket.on('ping', function (data) {
		console.log('ping', data);
		var now = new Date();
		var time = now.toISOString()
		console.log('pong', time )
		socket.emit('pong', time);
		
	});
	
	socket.on('broadcast', function (data) {
		console.log('broadcast', data);
		//~ socket.emit('broadcast', data.playerName);	
		socket.broadcast.emit('broadcast', data.playerName);	
	});
	

	socket.on('connect', function (data) {
		console.log('PRISIJUNGIMAS', data);
		matchId = data.matchId;
		playerId = data.playerId;
		action = data.action;
		secKey = data.secKey;
		
		//~ http.get("http://88.222.149.115/nodejs/demo", function(res) {//'gamex/check_match_info/'+matchId+'?player='+playerId+'&secretkey='+secKey
		var url = config.web2py_url+"check_match_info/"+matchId+'?player='+playerId+'&secretkey='+secKey
		//~ url = "http://jurgis.pythonanywhere.com/smartgames/game/check_match_info/21?player=3&secretkey=8804209"
		//url = "http://burgis.lt"
		//url = 'http://127.0.0.1:8080/'
		http.get(url, function(res) {
			if(res.statusCode == 200) {
				console.log('OK res.statusCode==200=True', url);
				//if(action == 'creator') {
					if( !(matchId in match) ) {
						match[matchId] = {}
						//game()['board'] = [[0, 0, 0],[0, 0, 0],[0, 0, 0]]
						game()['board'] = []
						for (var i = 0; i < x; i++) {
							game()['board'][i] = []
							for (var j = 0; j < y; j++)
								game()['board'][i][j] = 0;
						}
						
						http.get(config.web2py_url+'check_match_info/'+matchID+'?player_list', function(result) {
							result.on("data", function(body) {
								if(body != 'None' && body != 'wow\n')
									game()['playersId'] = body.slice(1,-1).split(', ');
							});
						})
						game()['playersSoc'] = []
						game()['playersType'] = ['x', 'o']
						//game()['firstPlayerType'] = 'x'
						game()['startType'] = 'x'
						game()['turnForType'] = 'x'
						//game()['secondPlayerId'] = 0
						//game()['secondPlayerType'] = 'o'
						game()['moves_log'] = []
						game()['sent'] = false
					}
					var validPlayer = false
					for(var i=0; i<game()['playersId'].length; ++i)
						if(game()['playersId'][i] == playerId) {
							validPlayer = true
							playerI = i
							game()['playersSoc'][playerI] = socket.id
							break
						}
					if(validPlayer) {
						//TODO: Check if disconnected???
						var allPlayers = true
						for(var i=0; i<game()['playersId'].length; ++i)
							if(game()['playersSoc'][i] == undefined) {//TODO:REVIEW
								allPlayers = false
								break
							}
								
						if(!AllPlayers) {
							for(var i=0; i<game()['playersId'].length; ++i)
								if(game()['playersSoc'][i] != undefined)
									io.sockets.socket(game()['playersSoc'][i]).emit('waiting');
						} else {
							for(var i=0; i<game()['playersId'].length; ++i)
								if(game()['playersSoc'][i] != undefined)
									io.sockets.socket(game()['playersSoc'][i]).emit(game()['playersType'][i] == game()['turnForType'] ? 'yourTurn' : 'notYourTurn');
						}
						/*
						if(game()['playersSoc'][1] == playerI)//Waiting
							io.sockets.socket(game()['firstPlayerId']).emit('waiting');
						else {
							if(!win(game()['board'])) {
								socket.emit(game()['firstPlayerType'] == game()['turnForType'] ? 'yourTurn' : 'notYourTurn');
								io.sockets.socket(game()['secondPlayerId']).emit(game()['secondPlayerType'] == game()['turnForType'] ? 'yourTurn' : 'notYourTurn');
							}
						}*/
					} else {	
						console.log('WARNING! The player is not valid according to web2py webserver');//TODO: NOTICE: send user friendly message
						//socket.emit('warning', '');
					}
				/*} else if(action == 'joined') {
					if( matchId in match ) {
						if(game()['secondPlayerId'] == 0)
							game()['secondPlayerId'] = socket.id
						if(!win(game()['board'])) {
							socket.emit(game()['secondPlayerType'] == game()['turnForType'] ? 'yourTurn' : 'notYourTurn');
							io.sockets.socket(game()['firstPlayerId']).emit(game()['firstPlayerType'] == game()['turnForType'] ? 'yourTurn' : 'notYourTurn');
						}
					}
				}*/

				//if(game()['firstPlayerId'] != game()['secondPlayerId'] 
				//	&& game()['secondPlayerId'] != 0)
				//TODO: Waiting for another player to join; Successfully joined.
			
	//		http.get("http://88.222.149.115/nodejs/demo", function(res) {
				//console.log("Got response: " + res.statusCode);
				//console.log(res);
				console.log('STATUS: ' + res.statusCode);
				//console.log('HEADERS: ' + JSON.stringify(res.headers));
				//res.on("data", function(chunk) {
				//	console.log("BODY:" + chunk);
				//});

				console.log('###########################');
				
				console.log(matchId, game())
				if( matchId in match )
					socket.emit('boardUpdate', game()['board']);
			} else {
				console.log('ERROR LOG: res.statusCode' + res.statusCode, url);
			}
		}).on('error', function(e) {
			  console.log("Got ERROR: " + e.message, url, e);
		});

	});

	//Actions:

	//ON:
	/*
	socket.on('newGame', function (data) {
		board = [[0, 0, 0],[0, 0, 0],[0, 0, 0]]	
		console.log('socket.on.newGame');
		console.log(socket.id);
		//console.log(socket.sessionId);
		firstPlayerId = socket.id;
		firstPlayerType = data.type;
		secondPlayerType = inv(firstPlayerType)// == 'x' ? 'o' : 'x';
		startType = data.startType;
		turnForType = startType;
		socket.emit('newGameData', socket.id);
		socket.emit('boardUpdate', board);
		io.sockets.socket(firstPlayerId).emit(firstPlayerType == turnForType ? 'yourTurn' : 'notYourTurn');
		if(secondPlayerId == socket.id)
			secondPlayerId = 0
		if(secondPlayerId != 0) {
			io.sockets.socket(secondPlayerId).emit('boardUpdate', board);
			//socket.broadcast.emit//All except sender
			//ocket.broadcast.to('room1').emit
			io.sockets.socket(secondPlayerId).emit(secondPlayerType == turnForType ? 'yourTurn' : 'notYourTurn');
		}
	});*/
	socket.on('move', function (data) {
		gameOver = win(game()['board'])
		if( (game()['board'][data.x][data.y] != 'o' && game()['board'][data.x][data.y] != 'x') &&
			gameOver == false && isYourTurn(matchId, socket.id)
		) {
			game()['turnForType'] = inv(game()['turnForType']);
			var c = game()['playersSoc'][0] == socket.id ? game()['playersType'][0] : game()['playersType'][1];
			game()['moves_log'].push({'x':data.x,'y':data.y,'t':c})
			game()['board'][data.x][data.y] = c;
			console.log('move');
			console.log(data);
			console.log(socket.id);
			//console.log(firstPlayerId);
			io.sockets.socket(game()['playersSoc'][0]).emit('boardUpdate', game()['board']);
			if(game()['playersSoc'][1] != undefined)
				io.sockets.socket(game()['playersSoc'][1]).emit('boardUpdate', game()['board']);
			newGameOver = win(game()['board'])
			if(newGameOver != false) {
				io.sockets.socket(game()['playersSoc'][0]).emit(newGameOver == game()['playersType'][0] ? 'won' : 'lose')//, {fin:newGameOver,ftype:firstPlayerType});
				io.sockets.socket(game()['playersSoc'][1]).emit(newGameOver == game()['playersType'][1] ? 'won' : 'lose')//, {fin:newGameOver,stype:secondPlayerType});
				//clear the board
				if('playersId' in game()) {
					winner = (newGameOver == game()['playersType'][0] ? game()['playersId'][0] : game()['playersId'][1]);
					http.get(config.web2py_url+'update_match_info/'+matchId+'/finish?winner='+winner+'&moves_log='+game()['moves_log'], function(res) {
						if(res.statusCode == 200) 
							game()['sent'] = true
					});
				} else {
					//another call to w2p for usersId?
				}
			} else {
				io.sockets.socket(game()['turnForType'] == game()['playersType'][0] ? game()['playersSoc'][0] : game()['playersSoc'][1]).emit('yourTurn');
				io.sockets.socket(game()['turnForType'] == game()['playersType'][1] ? game()['playersSoc'][0] : game()['playersSoc'][1]).emit('notYourTurn');
			}
			//socket.emit('boardUpdate', board);
		} else {
			console.log('Can\'t move. Is your turn:', isYourTurn(matchId, socket.id), '; gameOver=', gameOver == false, '; game()[\'board\'][data.x][data.y] != \'o\'', game()['board'][data.x][data.y] != 'o', '; game()[\'board\'][data.x][data.y] != \'x\'=', game()['board'][data.x][data.y] != 'x');
		}
	});
	socket.on('disconnect', function() {
		try {
			if       ( game()['playersSoc'][0] == socket.id ) {  // error ? (jei created nevyko..)
				game()['playersSoc'][0] = undefined
				game()['playersType'][0] = 'x';
				io.sockets.socket(game()['playersSoc'][1]).emit('disconnected');
			} else if( game()['playersSoc'][1] == socket.id ) {
				game()['playersSoc'][1] = undefined
				game()['playersType'][1] = 'o';
				io.sockets.socket(game()['playersSoc'][0]).emit('disconnected');
			}
		} catch(e) {console.log('CATCH: disconnected'+e)}
		console.log('disconnected');
	});
});

function win(grid) {
	//Rewrite to cycle [and transformations]?
	/*
	col=row=diag=rdiag=0
	winner=false
	for(var i=1; i<x; i++) {
		if grid[x,i]=player then col++
		if grid[i,y]=player then row++
		if grid[i,i]=player then diag++
		if grid[i,n-i+1]=player then rdiag++
		if row=n or col=n or diag=n or rdiag=n then winner=true
	*/
	//Rows
	for(var r=0; r<y; r++) {
		for(var c=0; c<x; c++) {
			if(grid[r][0] != grid[r][c])
				break;
			if(c == x-1 && (grid[r][0] == 'o' || grid[r][0] == 'x') )
				return true
		}
	}
	//Columns
	for(var c=1; c<x; c++) {
		for(var r=0; r<y; r++) {
			if(grid[0][c] != grid[r][c])
				break;
			if(r == y-1 && (grid[0][c] == 'o' || grid[0][c] == 'x') )
				return true
		}
	}

	if(grid[0][0] == grid[0][1] && grid[0][1] == grid[0][2] && grid[0][0] != 0)
		return grid[0][0]
	if(grid[1][0] == grid[1][1] && grid[1][1] == grid[1][2] && grid[1][0] != 0)
		return grid[1][0]
	if(grid[2][0] == grid[2][1] && grid[2][1] == grid[2][2] && grid[2][0] != 0)
		return grid[2][0]
	//Columns
	if(grid[0][0] == grid[1][0] && grid[1][0] == grid[2][0] && grid[0][0] != 0)
		return grid[0][0]
	if(grid[0][1] == grid[1][1] && grid[1][1] == grid[2][1] && grid[0][1] != 0)
		return grid[0][1]
	if(grid[0][2] == grid[1][2] && grid[1][2] == grid[2][2] && grid[0][2] != 0)
		return grid[0][2]
	//Diagonal					    
	if(grid[0][0] == grid[1][1] && grid[1][1] == grid[2][2] && grid[0][0] != 0)
		return grid[0][0]
	//Anti-diagonal Or minor
	if(grid[2][0] == grid[1][1] && grid[1][1] == grid[0][2] && grid[2][0] != 0)
		return grid[2][0]
	return false
}
/*
http://psitsmike.com/2011/10/node-js-and-socket-io-multiroom-chat-tutorial/
http://udidu.blogspot.com/2012/11/chat-evolution-nodejs-and-socketio.html
*/
